package com.iecm.tcp.handler;

import com.iecm.common.config.RabbitConfig;
import com.iecm.common.utils.DateUtil;
import com.iecm.common.utils.NettyUtil;
import com.iecm.common.utils.RabbitUtil;
import com.iecm.common.utils.RedisUtil;
import com.iecm.tcp.api.TcpServerApi;
import com.iecm.tcp.channel.TcpChannel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * tcp服务数据处理类
 */
@Component
@ChannelHandler.Sharable
@Slf4j
public class TcpServerHandler extends ChannelInboundHandlerAdapter {

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private TcpChannel tcpChannel;

	@Autowired
	private TcpServerApi tcpServerApi;

	@Autowired
	private RabbitUtil rabbitUtil;

	@Autowired
	private RabbitConfig rabbitConfig;

	/**
	 * 活跃的、有效的通道
	 * 第一次连接成功后进入的方法
	 *
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		//获取连接通道ip
		String ip = getRemoteAddress(ctx);
		String channelId = ctx.channel().id().asLongText();
		if(!redisUtil.hHasKey("netty-error", ip)){
			log.info("与通道号为" + channelId + "的客户端" + ip + "建立连接，通道开启！");
			//将tcp客户端的channel信息保存
			tcpChannel.addChannel(ctx.channel());

		}else{
			ctx.disconnect();
		}
	}

	/**
	 * 不活动的通道
	 * 连接丢失后执行的方法（client端可据此实现断线重连）
	 *
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
		String channelId = ctx.channel().id().asLongText();
		//根据通道id获取采集器id
		if(redisUtil.hHasValue("sys-netty", channelId)){
			String clientId = redisUtil.hgetValue("sys-netty", channelId).toString();
			//移除redis中保存的channel
			redisUtil.hdel("sys-netty", clientId);
			//添加离线时间
			redisUtil.hset("offline-time", clientId, DateUtil.getTime());

			log.error("与通道号为" + channelId + "的客户端" + clientId + "失去连接，通道关闭！");

			String msg = "与通道号为" + channelId + "的客户端" + clientId + "失去连接，通道关闭！";

			tcpServerApi.writeToAlarm(clientId, "1","3", "2", "失去连接", msg);
			tcpServerApi.writeToCollectorOnline(clientId,"0");
		}
		//移除tcp客户端的channel信息
		tcpChannel.removeChannel(ctx.channel());
		//断开连接
		ctx.disconnect();
	}

	/**
	 * 拿到传过来的msg数据，开始处理
	 *
	 * @param ctx
	 * @param msg
	 * @throws Exception
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		log.info("接收到采集器发送的数据：" + msg.toString());
		//获取管道id
		String channelId = ctx.channel().id().asLongText();
		String start = msg.toString().substring(0, 2);
		String end = msg.toString().substring(msg.toString().length() - 2);
		//if(start.equals())
		if (!start.equals("BB")) {
			if (redisUtil.hHasKey(channelId, "collector_type")) {
				//获取采集器关联设备信息
				String datas = redisUtil.hget(channelId, "collector_type").toString() + " " + msg.toString();
				if (end.equals("F0")) {
					redisUtil.hdel(channelId, "collector_type");
					//热表数据
					this.saveLink(datas);
				} else {
					redisUtil.hset(channelId, "collector_type", datas);
				}
			} else if (redisUtil.hHasKey(channelId, "meter_data")) {
				//查询热表阀门数据
				String datas = redisUtil.hget(channelId, "meter_data").toString() + " " + msg.toString();
				if (end.equals("F0")) {
					redisUtil.hdel(channelId, "meter_data");
					this.saveData(datas);
				} else {
					redisUtil.hset(channelId, "meter_data", datas);
				}
			} else if (redisUtil.hHasKey(channelId, "collector_data")) {
				//批量获取设备数据
				String datas = redisUtil.hget(channelId, "collector_data").toString() + " " + msg.toString();
				if (end.equals("F0")) {
					redisUtil.hdel(channelId, "collector_data");
					this.saveData(datas);
				} else {
					redisUtil.hset(channelId, "collector_data", datas);
				}
			} else if (redisUtil.hHasKey(channelId, "offline_data")) {
				//获取离线数据
				String datas = redisUtil.hget(channelId, "offline_data").toString() + " " + msg.toString();
				if (end.equals("F0")) {
					redisUtil.hdel(channelId, "offline_data");
					this.saveData(datas);
				} else {
					redisUtil.hset(channelId, "offline_data", datas);
				}
			} else if((start.equals("41")&&end.equals("0A")) || (start.equals("41")&&end.equals("2B"))) {
				String client = redisUtil.hgetValue("sys-netty", channelId).toString();
				log.error("接收到通道号为" + channelId + "的采集器" + client + "的测试数据" + msg.toString());
			}else {
				if (!redisUtil.hHasValue("sys-netty", channelId)) {
					log.error("接收到通道号为" + channelId + "的客户端" + getRemoteAddress(ctx) + "的非法数据，通道关闭！");
					redisUtil.hset("netty-error", getRemoteAddress(ctx), ctx.channel().id().asShortText());
					ctx.disconnect();
				} else {
					String client = redisUtil.hgetValue("sys-netty", channelId).toString();
					log.error("接收到通道号为" + channelId + "的采集器" + client + "的错误数据" + msg.toString());
				}
			}
			return;
		}
		//将客户端数据转换成数组格式
		String[] msgs = msg.toString().split(" ");
		//采集器id
		String clientId = msgs[2] + msgs[1];
		String address = "";
		String addressType = "";

		if (msgs[3].equals("00") && msgs[4].equals("00") && msgs[6].equals("00") && msgs[5].equals("00") ) {
			//单元阀阀门id
			address = String.valueOf(NettyUtil.get10HexNum(msgs[11]));
			addressType = "3";
		} else if(!msgs[3].equals("00")) {
			//热表id
			address = msgs[3] + msgs[4] + msgs[5] + msgs[6];
			addressType = "2";
		} else{
			//阀门id
			address = msgs[6]+msgs[5];
			addressType = "1";
		}
		//控制码
		String cont = msgs[7];
		//错误码
		String errcode = msgs[8];

		if (errcode.equals("00")) {
			//数据长度
			int datalength = NettyUtil.get10HexNum(msgs[9] + msgs[10]);
			int meterdatalength= msgs.length;
			if (cont.equals("11")) {
				log.info("接收到通道号为" + channelId + "的采集器" + clientId + "的心跳数据：" + msg.toString());
				//这里是心跳包,建立采集器与服务器链路
				if (redisUtil.hHasKey("sys-netty", clientId)) {
					String channelid = redisUtil.hget("sys-netty", clientId).toString();
					//判断通道号和redis中保存的通道号是否相同
					if (!channelid.equals(channelId)) {
						//保存上线时间
						redisUtil.hset("online-time", clientId, DateUtil.getTime());
						tcpServerApi.writeToCollectorOnline(clientId,"1");
					}
				} else {
					//保存上线时间
					redisUtil.hset("online-time", clientId, DateUtil.getTime());
					tcpServerApi.writeToCollectorOnline(clientId,"1");
				}
				//保存连接属性
				redisUtil.hset("sys-netty", clientId, channelId);
				//计算校验码
				int ll = NettyUtil.get10HexNum(msgs[1]) + NettyUtil.get10HexNum(msgs[2]) + NettyUtil.get10HexNum(cont);
				String check = NettyUtil.get16HexNum(ll);
				if (check.length() < 2) {
					check = "0" + check;
				} else {
					check = check.substring(check.length() - 2);
				}
				String response = "AA " + msgs[1] + " " + msgs[2] + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
				String revertStr = response.replace(" ", "");
				tcpChannel.writeToClient(channelId, revertStr, "心跳数据");
			} else if (cont.equals("01")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的设备采集数据：" + msg.toString());
				//这里是查询数据结果
				if (end.equals("F0")) {
					String datas = NettyUtil.strChange(msgs, 11, datalength);

					String meterDatas = NettyUtil.strChange(msgs, 0, meterdatalength);

					if (addressType.equals("1")) {
						this.saveValve(datas, DateUtil.getNowDate(),clientId);
					} else if(addressType.equals("2")) {
						this.saveMeter(meterDatas, DateUtil.getNowDate());
					}
					redisUtil.hset(address, cont, errcode, 50);
				} else {
					//保存到redis
					redisUtil.hset(channelId, "meter_data", msg.toString());
				}

			} else if (cont.equals("02")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的设置阀门开度数据：" + msg.toString());
				//这里是设置阀门开度
				redisUtil.hset(address, cont, errcode, 10);
			} else if (cont.equals("03")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的设备登记数据：" + msg.toString());
				//这里是设备登记
				redisUtil.hset(address, cont, errcode, 10);
			} else if (cont.equals("04")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的设备注销数据：" + msg.toString());
				//这里是设备注销
				redisUtil.hset(address, cont, errcode, 10);
			} else if (cont.equals("05")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的设备批量采集数据：" + msg.toString());
				if (end.equals("F0")) {
					//这里是批量设备获取数据
					String datas = NettyUtil.strChange(msgs, 11, datalength);
					String meterDatas = NettyUtil.strChange(msgs, 0, meterdatalength);
					if (addressType.equals("1")) {
						this.saveValve(datas, DateUtil.getNowDate(),clientId);
					} else if (addressType.equals("2")) {
						this.saveMeter(meterDatas, DateUtil.getNowDate());
					}
				} else {
					//保存到redis
					redisUtil.hset(channelId, "collector_data", msg.toString());
				}
			} else if (cont.equals("06")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的批量设置阀门开度数据：" + msg.toString());
				//这里是批量设置阀开度
				redisUtil.hset(clientId, cont, errcode, 10);
			} else if (cont.equals("07")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的离线抄表时间数据：" + msg.toString());
				//这里是离线设置抄表时间
				redisUtil.hset(clientId, cont, errcode, 10);
			} else if (cont.equals("08")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的设置心跳时间数据：" + msg.toString());
				//这里是设置心跳时间
				redisUtil.hset(clientId, cont, errcode, 10);
			} else if (cont.equals("09")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的限制阀门开启数据：" + msg.toString());
				//这里是限制阀门开启
				redisUtil.hset(address, cont, errcode, 10);
			} else if (cont.equals("0A")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的初始化数据：" + msg.toString());
				//这里是采集器初始化
				this.saveInit(clientId);
				redisUtil.hdel("sys-netty", clientId);
				redisUtil.hset("offline-time", clientId, DateUtil.getTime());
				redisUtil.hset(clientId, cont, errcode, 10);
				tcpChannel.removeChannel(ctx.channel());
			} else if (cont.equals("0B")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的校准时间数据：" + msg.toString());
				//这里是校准时间
				redisUtil.hset(clientId, cont, errcode, 10);
			} else if (cont.equals("0C")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的获取关联设备数据：" + msg.toString());
				//这里是获取采集器关联设备信息
				if (end.equals("F0")) {
					//保存设备类型
					this.saveLink(msg.toString());
				} else {
					//保存到redis
					redisUtil.hset(channelId, "collector_type", msg.toString());
				}
			} else if (cont.equals("0D")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的查看采集器时间数据：" + msg.toString());
				//这里是查看采集器时间
				String datas = NettyUtil.strChange(msgs, 11, datalength);
				String[] dd = datas.split(" ");
				String time = "20" + dd[0] + "-" + dd[1] + "-" + dd[2] + " " + dd[3] + ":" + dd[4];
				//将数据保存redis
				redisUtil.hset(clientId, cont, time, 10);
			} else if (cont.equals("0E")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的离线结束数据：" + msg.toString());
				//这里是批量操作结束符
				int datacount = (Integer) redisUtil.hget(channelId, "10");
				log.info("datacount====="+datacount);
				if (datacount == 0) {
					redisUtil.hdel(channelId, "10");
					//计算校验码
					int ll = NettyUtil.get10HexNum(msgs[1]) + NettyUtil.get10HexNum(msgs[2]) + NettyUtil.get10HexNum(cont);
					String check = NettyUtil.get16HexNum(ll);
					if (check.length() < 2) {
						check = "0" + check;
					} else {
						check = check.substring(check.length() - 2);
					}
					String response = "AA " + msgs[1] + " " + msgs[2] + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
					String revertStr = response.replace(" ", "");
					tcpChannel.writeToClient(channelId, revertStr, "数据接收完毕");
				} else {
					int contcount = 0;
					if (redisUtil.hHasKey(channelId, cont)) {
						contcount = (Integer) redisUtil.hget(channelId, cont) + 1;
					} else {
						contcount = 1;
					}
					if (contcount >= 5) {
						redisUtil.hdel(channelId, "10");
						redisUtil.hdel(channelId, cont);
						//计算校验码
						int ll = NettyUtil.get10HexNum(msgs[1]) + NettyUtil.get10HexNum(msgs[2]) + NettyUtil.get10HexNum(cont);
						String check = NettyUtil.get16HexNum(ll);
						if (check.length() < 2) {
							check = "0" + check;
						} else {
							check = check.substring(check.length() - 2);
						}
						String response = "AA " + msgs[1] + " " + msgs[2] + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
						String revertStr = response.replace(" ", "");
						tcpChannel.writeToClient(channelId, revertStr, "数据接收错误");
					}else{
						redisUtil.hset(channelId, cont, contcount);
					}
				}
			} else if (cont.equals("0F")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的MBUS过载数据：" + msg.toString());
				//这里是MUBS过载
				//计算校验码
				int ll = NettyUtil.get10HexNum(msgs[1]) + NettyUtil.get10HexNum(msgs[2]) + NettyUtil.get10HexNum(cont);
				String check = NettyUtil.get16HexNum(ll);
				if (check.length() < 2) {
					check = "0" + check;
				} else {
					check = check.substring(check.length() - 2);
				}
				String response = "AA " + msgs[1] + " " + msgs[2] + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
				String revertStr = response.replace(" ", "");
				tcpChannel.writeToClient(channelId, revertStr, "MBUS过载警告");
				String msgss ="接收到通道号为" + channelId + "的采集器的" + clientId + "的MBUS过载数据";
				tcpServerApi.writeToAlarm(clientId, "1","3", "1", "MBUS过载警告", msgss);
			} else if (cont.equals("10")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的离线传输请求数据：" + msg.toString());
				//获取数据内容
				String[] datass = NettyUtil.strsChange(msgs, 11, datalength);
				int datacount = 0;
				for (int i = 0; i < datass.length; i++) {
					int m = 11 + i;
					datacount += NettyUtil.get10HexNum(msgs[m]);
				}
				log.info("tcp客户端" + getRemoteAddress(ctx) + "总共" + datacount + "条离线数据待传输");
				//将总数居记录保存到redis
				redisUtil.hset(channelId, cont, datacount, 1000*60*60);
				//计算校验码
				int ll = NettyUtil.get10HexNum(msgs[1]) + NettyUtil.get10HexNum(msgs[2]) + NettyUtil.get10HexNum(cont);
				String check = NettyUtil.get16HexNum(ll);
				if (check.length() < 2) {
					check = "0" + check;
				} else {
					check = check.substring(check.length() - 2);
				}
				String response = "AA " + msgs[1] + " " + msgs[2] + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
				String revertStr = response.replace(" ", "");
				tcpChannel.writeToClient(channelId, revertStr, "离线传输数据开始");
			} else if (cont.equals("12")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的离线设备数据：" + msg.toString());
				//这里是获取离线设备数据
				redisUtil.hdecr(channelId, "10", 1);
				String time = "20" + msgs[11] + "-" + msgs[12] + "-" + msgs[13] + " " + msgs[14] + ":" + msgs[15];
				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
				Date createTime = null;
				try {
					createTime = dateFormat.parse(time);
				} catch (ParseException e) {
					e.printStackTrace();
				}
				if (end.equals("F0")) {
					String datas = NettyUtil.strChange(msgs, 22, datalength - 11);
					String meterDatas =NettyUtil.strChange(msgs, 0, 11) +" "+ NettyUtil.strChange(msgs, 22, meterdatalength - 11);

					if (addressType.equals("1")) {
						this.saveValve(datas, createTime,clientId);
					} else if(addressType.equals("2")) {
						this.saveMeter(meterDatas, createTime);
					}
				} else {
					//保存到redis
					redisUtil.hset(channelId, "offline_data", msg.toString());
				}
			} else if (cont.equals("13")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的修改服务器地址数据：" + msg.toString());
				//这里是修改服务器地址
				redisUtil.hset(clientId, cont, errcode, 10);
				redisUtil.hdel("sys-netty", clientId);
				redisUtil.hdel("online-time", clientId);
				if(redisUtil.hHasKey("offline-time", clientId)){
					redisUtil.hdel("offline-time", clientId);
				}
				//移除tcp客户端的channel信息
				tcpChannel.removeChannel(ctx.channel());
			} else if(cont.equals("14")){
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的单元阀寄存器读取数据：" + msg.toString());
				//这里是查询数据结果
				if (end.equals("F0")) {
					String datas = NettyUtil.strChange(msgs, 11, datalength);
					if (addressType.equals("1")) {
						this.saveValve(datas, DateUtil.getNowDate(),clientId);
					} else if(addressType.equals("2")) {
						this.saveMeter(msgs.toString(), DateUtil.getNowDate());
					} else if(addressType.equals("3")){
						this.saveUnitValve(datas, DateUtil.getNowDate());
					}

					redisUtil.hset(address, cont, errcode, 10);
				} else {
					//保存到redis
					redisUtil.hset(channelId, "unitValve_data", msg.toString());
				}


			}else if (cont.equals("15")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的单元阀寄存器写入数据：" + msg.toString());
				//单元阀寄存器写入
				redisUtil.hset(address, cont, errcode, 10);
			}else if (cont.equals("16")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "挂载的所有阀门批量采集数据：" + msg.toString());
				if (end.equals("F0")) {
					//这里是批量设备获取数据
					String datas = NettyUtil.strChange(msgs, 11, datalength);
					if (addressType.equals("1")) {
						this.saveValve(datas, DateUtil.getNowDate(),clientId);
					} else if (addressType.equals("2")) {
						this.saveMeter(msgs.toString(), DateUtil.getNowDate());
					}
				} else {
					//保存到redis
					redisUtil.hset(channelId, "collector_data", msg.toString());
				}
			}else if (cont.equals("17")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "挂载的所有热表批量采集数据：" + msg.toString());
				if (end.equals("F0")) {
					//这里是批量设备获取数据
					String datas = NettyUtil.strChange(msgs, 11, datalength);
					String meterDatas = NettyUtil.strChange(msgs, 0, meterdatalength);
					if (addressType.equals("1")) {
						this.saveValve(datas, DateUtil.getNowDate(),clientId);
					} else if (addressType.equals("2")) {
						this.saveMeter(meterDatas, DateUtil.getNowDate());
					}
				} else {
					//保存到redis
					redisUtil.hset(channelId, "collector_data", msg.toString());
				}
			}else if (cont.equals("18")){
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "批量采集完成" + msg.toString());

			}else if (cont.equals("19")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的下发供暖和非供暖标志：" + msg.toString());
				//这里是批量设置阀开度
				redisUtil.hset(clientId, cont, errcode, 10);
			}else if (cont.equals("1A")) {
				log.info("接收到通道号为" + channelId + "的采集器的" + clientId + "的阀门新B6指令下发与接收：" + msg.toString());
				//这里是阀门新B6指令下发与接收
				String datas = NettyUtil.strChange(msgs, 11, datalength);
				String[] dd = datas.split(" ");
				String time = dd[6];
				//将数据保存redis
				redisUtil.hset(address, cont, time, 10);
			}

		} else {
			log.error("通道号为" + channelId + "的客户端" + clientId + "错误数据：" + msg.toString());
			String alarmMsg = "通道号为" + channelId + "的客户端" + address + "错误数据：" + msg.toString();
			redisUtil.hset(address, cont, errcode, 10);
			tcpServerApi.writeToAlarm(address,"1", addressType, "2", "错误数据", alarmMsg);}
	}

	/**
	 * 服务端接收客户端发送过来的数据结束之后调用
	 * @param ctx
	 * @throws Exception
	 */
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		super.channelReadComplete(ctx);
	}

	/**
	 * 异常处理
	 *
	 * @param ctx
	 * @param cause
	 * @throws Exception
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		super.exceptionCaught(ctx, cause);
		String channelId = ctx.channel().id().asLongText();
		log.error("通道号为" + channelId + "的客户端" + getRemoteAddress(ctx) + "通道发生异常，数据无法解析：" + cause.getMessage());
	}

	/**
	 * 心跳机制，超时处理
	 *
	 * @param ctx
	 * @param evt
	 * @throws Exception
	 */
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		String channelId = ctx.channel().id().asLongText();
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent event = (IdleStateEvent) evt;
			String clientId = "";
			if(redisUtil.hHasValue("sys-netty", channelId)) {
				clientId = redisUtil.hgetValue("sys-netty", channelId).toString();
			}
			if (event.state() == IdleState.READER_IDLE) {
				log.error("通道号为" + channelId + "的客户端" + clientId + "读超时，连接中断");
				ctx.disconnect();
			} else if (event.state() == IdleState.WRITER_IDLE) {
				log.error("通道号为" + channelId + "的客户端" + clientId + "写超时，连接中断");
			} else if (event.state() == IdleState.ALL_IDLE) {
				if(!clientId.equals("")){
					//获取采集器高位
					String cenhigh = clientId.substring(0,2);
					//获取采集器低位
					String cenlow = clientId.substring(2,4);
					//计算校验码
					int ll = NettyUtil.get10HexNum(cenhigh) + NettyUtil.get10HexNum(cenlow) + NettyUtil.get10HexNum("11");
					String check = NettyUtil.get16HexNum(ll);
					if (check.length() < 2) {
						check = "0" + check;
					} else {
						check = check.substring(check.length() - 2);
					}
					String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 11 00 00 00 00 00 00 " + check + " FF ";
					String revertStr = response.replace(" ", "");
					tcpChannel.writeToClient(channelId, revertStr, "超时抢救");
				}
			}
		}
	}

	/**
	 * 获取client对象：ip
	 *
	 * @param ctx
	 * @return
	 */
	private String getRemoteAddress(ChannelHandlerContext ctx) {
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
		String ip = insocket.getAddress().getHostAddress();
		return ip;
	}

	/**
	 * 异步保存数据
	 * @param datas
	 */
	private void saveData(String datas){
		//将客户端数据转换成数组格式
		String[] msgs = datas.split(" ");
		//控制码
		String cont = msgs[7];
		//错误码
		String errcode = msgs[8];
		String address = "";
		String addressType = "";
		String clientId=msgs[2]+msgs[1];

		if (msgs[3].equals("00") && msgs[4].equals("00") && msgs[6].equals("00") && msgs[5].equals("00") ) {
			//单元阀阀门id
			address = msgs[11];
			addressType = "3";
		} else if(!msgs[3].equals("00")) {
			//热表id
			address = msgs[3] + msgs[4] + msgs[5] + msgs[6];
			addressType = "2";
		} else{
			//阀门id
			address = msgs[6]+msgs[5];
			addressType = "1";
		}
		//数据长度
		int datalength = NettyUtil.get10HexNum(msgs[9] + msgs[10]);
		int meterdatalength= msgs.length;
		datas = NettyUtil.strChange(msgs, 11, datalength);
		String meterDatas = NettyUtil.strChange(msgs, 0, meterdatalength);
		if (addressType.equals("1")) {
			this.saveValve(datas, DateUtil.getNowDate(),clientId);
		} else if(addressType.equals("2")) {
			this.saveMeter(meterDatas, DateUtil.getNowDate());
		}else if(addressType.equals("3")){
			this.saveUnitValve(datas, DateUtil.getNowDate());
		}
		redisUtil.hset(address, cont, errcode, 10);
	}

	/**
	 * 异步保存阀门数据
	 * @param datas
	 */
	private void saveValve(String datas, Date createTime,String clientId){
		tcpServerApi.writeToValve(datas, createTime,clientId);
	}

	/**
	 * 异步保存热表数据
	 * @param meterDatas
	 */
	private void saveMeter(String meterDatas, Date createTime){
		tcpServerApi.writeToMeter(meterDatas, createTime);
	}
	/**
	 * 异步保存单元阀阀门数据
	 * @param datas
	 */
	private void saveUnitValve(String datas, Date createTime){
		tcpServerApi.writeToUnitValve(datas, createTime);
	}


	/**
	 * 异步保存采集器关联设备信息
	 * @param datas
	 */
	private void saveLink(String datas){
		tcpServerApi.writeToCollector(datas, 1);
	}

	/**
	 * 异步保存采集器初始化信息
	 * @param datas
	 */
	private void saveInit(String datas){
		tcpServerApi.writeToCollector(datas, 2);
	}

}
